package com.yeskery.boot.log.record.starter.parser;

import com.yeskery.boot.log.record.starter.core.LogRecordContext;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.ParameterNameDiscoverer;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * 日志记录SpEL执行环境上下文
 * @author dushuangjiang
 * @date 2021-11-11 17:29
 */
public class LogRecordEvaluationContext extends MethodBasedEvaluationContext {
    /**
     * 构建日志记录SpEL执行环境上下文
     * @param rootObject 原始对象
     * @param method 方法对象
     * @param arguments 方法参数
     * @param parameterNameDiscoverer 参数名称发现器
     * @param ret 方法的返回结果
     * @param errorMsg 方法的执行的错误信息
     */
    public LogRecordEvaluationContext(Object rootObject, Method method, Object[] arguments,
                                      ParameterNameDiscoverer parameterNameDiscoverer, Object ret, String errorMsg) {
        //把方法的参数都放到 SpEL 解析的 RootObject 中
        super(rootObject, method, arguments, parameterNameDiscoverer);
        putLogRecordContext();
        putExecuteResult(ret, errorMsg);
    }

    /**
     * 构建日志记录SpEL执行环境上下文
     * @param rootObject 原始对象
     * @param method 方法对象
     * @param arguments 方法参数
     * @param parameterNameDiscoverer 参数名称发现器
     */
    public LogRecordEvaluationContext(Object rootObject, Method method, Object[] arguments,
                                      ParameterNameDiscoverer parameterNameDiscoverer) {
        //把方法的参数都放到 SpEL 解析的 RootObject 中
        super(rootObject, method, arguments, parameterNameDiscoverer);
    }

    /**
     * 把 LogRecordContext 中的变量都放到 RootObject 中
     */
    public void putLogRecordContext() {
        //把 LogRecordContext 中的变量都放到 RootObject 中
        Map<String, Object> variables = LogRecordContext.getVariables();
        if (variables != null && variables.size() > 0) {
            for (Map.Entry<String, Object> entry : variables.entrySet()) {
                setVariable(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 把方法的返回值和 ErrorMsg 都放到 RootObject 中
     * @param ret 方法的返回值
     * @param errorMsg 方法的ErrorMsg
     */
    public void putExecuteResult(Object ret, String errorMsg) {
        //把方法的返回值和 ErrorMsg 都放到 RootObject 中
        setVariable("_ret", ret);
        setVariable("_errorMsg", errorMsg);
    }
}
